package com.zycoin.pagehelp.mybatis;

import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.RowBounds;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 数据库方言，针对不同数据库进行实现
 */
public abstract class Dialect {

    /**
     * 默认获取查询分页总数sql，去除order by
     * @param sql
     * @return
     */
    public String getCountSql(String sql) {
        if (sql.contains("order by") || sql.contains("ORDER BY")) {
            sql = new CountSqlParser().getSmartCountSql(sql);
        }
        return "select count(0) from (" + sql + ") a";
    }

    /**
     * 查询总数
     * @param statementHandler
     * @param connection
     * @param sql
     * @param page
     * @throws SQLException
     */
    public void getTotal(StatementHandler statementHandler, Connection connection, String sql, Page<?> page) throws SQLException {
        ParameterHandler parameterHandler = statementHandler.getParameterHandler();
        PreparedStatement prepareStatement = connection.prepareStatement(sql);
        parameterHandler.setParameters(prepareStatement);
        ResultSet rs = prepareStatement.executeQuery();
        int count = 0;
        if (rs.next()) {
            count = rs.getInt(1);
        }
        rs.close();
        prepareStatement.close();
        page.setTotal(count);

    }

    /**
     * 获取分页查询 sql
     *
     * @param page
     * @param sql
     * @return
     */
    public abstract String getPageSql(Page<?> page, String sql);

    /**
     * 处理分页查询前数据
     * @param metaStatementHandler
     * @param sql
     * @param page
     */
    public void processPageInfo(MetaObject metaStatementHandler, String sql, Page<?> page) {
        processDialectPageInfo(metaStatementHandler,sql,page);
        // 屏蔽mybatis原有分页
        metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);
        metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);
    }

    /**
     * 方言特殊处理
     * @param metaStatementHandler
     * @param sql
     * @param page
     */
    public abstract void processDialectPageInfo(MetaObject metaStatementHandler, String sql, Page<?> page);

}
